/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
 */

package com.kaihong.template.utils;

import ohos.app.Context;
import ohos.bundle.IBundleManager;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * PermissionManager is used to check and request permission from users.
 *
 * @author cWX1042997
 * @since 2021-06-21
 */
public class PermissionManager {
    private static final int PERMISSION_REQ_CODE = 1000;

    private static final String TAG = "PermissionManager";

    private Context context;

    private final HashMap<Integer, PermissionStateCallback> callbackHashMap = new HashMap<>();

    /**
     * Construction method. Authorization callback needs to be transferred because authorization is not synchronized.
     *
     * @param context context
     */
    public PermissionManager(Context context) {
        this.context = context;
    }

    /**
     * set the context
     *
     * @param context context
     */
    public void setContext(Context context) {
        this.context = context;
    }

    /**
     * Check whether the permission is granted. returned with the callback
     *
     * @param permissions the permissions which need to apply
     * @param permissionStateCallback permission callback
     */
    public void checkPermissions(List<String> permissions, PermissionStateCallback permissionStateCallback) {
        if (permissions != null && !permissions.isEmpty() && permissionStateCallback != null) {
            List<String> grantedPermissions = new ArrayList<>();
            List<String> canRequestPermissions = new ArrayList<>();
            for (String permission : permissions) {
                if (permission == null || context == null) {
                    continue;
                }
                if (context.verifySelfPermission(permission) != IBundleManager.PERMISSION_GRANTED) {
                    Logger.i(TAG, "has no permission : " + permission);
                    if (context.canRequestPermission(permission)) {
                        canRequestPermissions.add(permission);
                    } else {
                        Logger.i(
                            TAG, "Context " + context.getClass().getName() + " can not request permissions.");
                    }
                } else {
                    Logger.i(TAG, "has permission : " + permission);
                    grantedPermissions.add(permission);
                }
            }
            permissionStateCallback.onPermissionResult(permissions, grantedPermissions, canRequestPermissions);
        }
    }

    /**
     * Applying for Permissions from Users
     *
     * @param permissions Permissions to be applied for
     * @param requestCode request code
     * @param permissionStateCallback apply permissions state callback
     */
    public void requestPermissions(
        List<String> permissions, int requestCode, PermissionStateCallback permissionStateCallback) {
        if (permissionStateCallback == null) {
            return;
        }
        if (permissions != null && permissions.size() > 0) {
            String[] permissionsArray = permissions.toArray(new String[0]);
            callbackHashMap.put(requestCode, permissionStateCallback);
            context.requestPermissionsFromUser(permissionsArray, requestCode);
        } else {
            permissionStateCallback.onPermissionResult(permissions, new ArrayList<>(), new ArrayList<>());
        }
    }

    /**
     * Permission grant callback, parses whether to grant location permission, and invokes the authorization callback
     * to notify the upper layer.
     *
     * @param requestCode request code
     * @param permissions Permissions to be applied for
     * @param grantResults granted permissions
     */
    public void onPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
        if (permissions == null || grantResults == null) {
            return;
        }
        List<String> permissionGranted = new ArrayList<>();
        List<String> canRequestPermissions = new ArrayList<>();
        for (int index = 0; index < permissions.length; index++) {
            if (grantResults[index] == IBundleManager.PERMISSION_GRANTED) {
                permissionGranted.add(permissions[index]);
            } else {
                if (context != null && context.canRequestPermission(permissions[index])) {
                    canRequestPermissions.add(permissions[index]);
                }
            }
        }
        if (callbackHashMap != null
            && callbackHashMap.containsKey(requestCode)
            && callbackHashMap.get(requestCode) != null) {
            callbackHashMap
                .get(requestCode)
                .onPermissionResult(Arrays.asList(permissions), permissionGranted, canRequestPermissions);
            callbackHashMap.remove(requestCode);
        }
    }
}
